// 包声明，指定该接口所属的包
package com.yupi.yuaicodemother.ai.rag;

// 导入 Document 类，用于表示文档对象
import dev.langchain4j.data.document.Document;
// 导入 Filter 类，用于在嵌入存储中进行过滤操作
import dev.langchain4j.store.embedding.filter.Filter;

// 导入 List 接口，用于处理列表数据
import java.util.List;
// 导入 Optional 类，用于处理可能为空的值
import java.util.Optional;

/**
 * EmbeddingStore 接口定义了嵌入存储的基本操作，用于管理文档的嵌入表示。
 * 该接口提供了添加、删除文档以及相似性搜索等功能，同时也提供了一些默认方法。
 */
public interface EmbeddingStore {

    /**
     * 获取嵌入存储实现类的名称。
     * 默认实现返回当前类的简单名称，子类可以根据需要重写此方法。
     * 
     * @return 当前类的简单名称
     */
    default String getName() {
        return this.getClass().getSimpleName();
    }

    /**
     * 向嵌入存储中添加一组文档。
     * 
     * @param documents 要添加的文档列表
     */
    void add(List<Document> documents);

    /**
     * 根据文档 ID 列表从嵌入存储中删除对应的文档。
     * 
     * @param idList 要删除的文档的 ID 列表
     */
    void delete(List<String> idList);

    /**
     * 根据过滤条件从嵌入存储中删除符合条件的文档。
     * 
     * @param filter 过滤条件对象
     */
    void delete(Filter filter);

    /**
     * 根据过滤表达式从嵌入存储中删除符合条件的文档。
     * 默认实现构造了一个总是返回 false 的 Filter 对象，子类需要根据实际需求重写此方法。
     * 
     * @param filterExpression 过滤表达式，用于构造过滤条件
     */
    default void delete(String filterExpression) {
        // 默认实现可以根据 filterExpression 构造 Filter 对象并调用 delete(Filter) 方法
        // 具体实现可以根据需要覆盖此方法
        delete(new Filter() {
            @Override
            public boolean test(Object o) {
                return false;
            }
        });
    }

    /**
     * 根据查询字符串在嵌入存储中进行相似性搜索，返回与查询最相似的文档列表。
     * 
     * @param query 查询字符串
     * @return 与查询最相似的文档列表
     */
    List<Document> similaritySearch(String query);

    /**
     * 根据搜索请求对象在嵌入存储中进行相似性搜索，返回与请求匹配的文档列表。
     * 注意：SearchRequest 类未在当前代码中展示，使用时需确保该类存在。
     * 
     * @param request 搜索请求对象
     * @return 与请求匹配的文档列表
     */
    List<Document> similaritySearch(SearchRequest request);

    /**
     * 获取嵌入存储的原生客户端对象。
     * 默认实现返回一个空的 Optional 对象，子类可以根据需要重写此方法以返回实际的原生客户端。
     * 
     * @param <T> 原生客户端对象的类型
     * @return 包含原生客户端对象的 Optional，若不存在则返回空的 Optional
     */
    default <T> Optional<T> getNativeClient() {
        return Optional.empty();
    }
}